package com.icare.common.service.utils;

import com.alibaba.druid.util.HexBin;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.Key;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.Random;

/**
 * 密码加密解密工具
 *
 * @author TianHaibo
 * @create 2018-01-13 19:47
 **/
public class PasswordUtil {

private static final String SECURE_IV = "@tianhaibo&!1234";

private static final String SECURE_KEY = "!1234&tianhaibo@";

private static final String SALT = "&tianhaibo@";


    /**
     * SHA加密
     * @param clear
     * @return
     */
    public static String  encryptSHA(String clear) throws NoSuchAlgorithmException {
        //选用sha加密算法
        MessageDigest messageDigest = MessageDigest.getInstance("SHA");
        //明文加密
        messageDigest.update(clear.getBytes());
        return HexBin.encode(messageDigest.digest());//字节密文转成十六进制字符串
    }


    public static String encryptPassword(String clear){
        try {
            return encryptPassword(clear,SECURE_KEY,SECURE_IV);
        } catch (Exception e) {
            e.printStackTrace();return null;
        }
    }

    public static String decryptPassword(String password){
        try {
            return decryptPassword(password,SECURE_KEY,SECURE_IV);
        } catch (Exception e) {
            e.printStackTrace();return null;
        }
    }
    /**
     *  AES加密
     * @param clear 明文
     * @param secureKey 安全密钥(长度必须是16/24/32字节)
     * @param secureIv  初始向量(必须是16字节长度)
     * @return  密文
     * @throws Exception
     */
    public static String encryptPassword(String clear ,String secureKey,String secureIv) throws Exception {
        Key keySpec = new SecretKeySpec(secureKey.getBytes(), "AES");
        IvParameterSpec ivSpec = new IvParameterSpec(secureIv.getBytes());
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(1, keySpec, ivSpec);
        return Base64.getEncoder().encodeToString(cipher.doFinal(clear.getBytes()));
    }

    /**
     * AES解密
     * @param password  密文
     * @param secureKey 安全密钥(长度必须是16/24/32字节)
     * @param secureIv  初始向量(必须是16字节长度)
     * @return  明文
     * @throws Exception
     */
    public static String decryptPassword(String password,String secureKey,String secureIv) throws Exception {
        byte[] bytes = Base64.getDecoder().decode(password);
        IvParameterSpec ivSpec = new IvParameterSpec(secureIv.getBytes());
        Key key = new SecretKeySpec(secureKey.getBytes(), "AES");
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(2, key, ivSpec);
        byte[] ret = cipher.doFinal(bytes);
        return new String(ret, "utf-8");
    }

    /**
     * 生成含有随机盐的密码,其实就是相当于把动态盐和md5值放在一起
     */
    public static String generate(String password) {
        Random r = new Random();
        StringBuilder sb = new StringBuilder(16);
        sb.append(r.nextInt(99999999)).append(r.nextInt(99999999));
        int len = sb.length();
        if (len < 16) {
            for (int i = 0; i < 16 - len; i++) {
                sb.append("0");
            }
        }
        String salt = sb.toString();
        password = md5Hex(password + salt);

        char[] cs = new char[48];
        for (int i = 0; i < 48; i += 3) {
            cs[i] = password.charAt(i / 3 * 2);
            cs[i + 1] = salt.charAt(i / 3);
            cs[i + 2] = password.charAt(i / 3 * 2 + 1);
        }
        return new String(cs);
    }

    /**
     * 校验密码是否正确
     */
    public static boolean verify(String password, String md5) {
        char[] cs1 = new char[32];
        char[] cs2 = new char[16];
        for (int i = 0; i < 48; i += 3) {
            cs1[i / 3 * 2] = md5.charAt(i);
            cs1[i / 3 * 2 + 1] = md5.charAt(i + 2);
            cs2[i / 3] = md5.charAt(i + 1);
        }
        String salt = new String(cs2);
        return md5Hex(password + salt).equals(new String(cs1));
    }

    /**
     * 获取十六进制字符串形式的MD5摘要
     */
    public static String md5Hex(String src) {
        try {
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            byte[] bs = md5.digest(src.getBytes());

            return HexBin.encode(bs);
        } catch (Exception e) {
            return null;
        }
    }

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            String password = generate("admin");
            System.out.println(password);
        }
    }
}
